package com.chenbei.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenbei.common.exception.LogicHandleException;
import com.chenbei.common.util.TreeNodeUtil;
import com.chenbei.common.domain.vo.TreeNode;
import com.chenbei.system.domain.SysMenu;
import com.chenbei.system.enums.SysMenuTypeEnum;
import com.chenbei.system.mapper.SysMenuMapper;
import com.chenbei.system.service.ISysMenuService;
import com.chenbei.system.service.ISysRoleMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SysMenuService extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Autowired
    private ISysRoleMenuService roleMenuService;

    @Override
    public void add(SysMenu menu) {
        if (menu.getPid() == null) {
            menu.setPid(0L);
        }
        if (menu.getSort() == null || menu.getSort() <= 0) {
            menu.setSort(1);
        }
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysMenu::getName, menu.getName()).eq(SysMenu::getPid, menu.getPid());
        if (count(lambdaQueryWrapper) > 0) {
            throw new LogicHandleException("菜单名称已存在");
        }
        validate(menu);
        save(menu);
    }

    @Override
    public void deleteById(Long id) {
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysMenu::getPid, id);
        if (count(lambdaQueryWrapper) > 0) {
            throw new LogicHandleException("存在子节点，禁止删除操作");
        }
        removeById(id);
    }

    @Override
    public void update(SysMenu menu) {
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysMenu::getName, menu.getName())
                .eq(SysMenu::getPid, menu.getPid())
                .ne(SysMenu::getId, menu.getId());
        if (count(lambdaQueryWrapper) > 0) {
            throw new LogicHandleException("菜单名称已存在");
        }
        validate(menu);
        if (Objects.equals(menu.getId(), menu.getPid())) {
            SysMenu oldMenu = getById(menu.getId());
            if (oldMenu != null) {
                menu.setPid(oldMenu.getPid());
            }
        }
        updateById(menu);
    }

    @Override
    public List<SysMenu> listByPid(Long pid) {
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysMenu::getPid, pid)
                .orderByAsc(SysMenu::getSort)
                .orderByAsc(SysMenu::getId);
        return list(lambdaQueryWrapper);
    }

    @Override
    public List<TreeNode<SysMenu>>  allTree() {
        LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(SysMenu::getSort)
                .orderByAsc(SysMenu::getId)
                .eq(SysMenu::getStatus, 1); // 只查询状态为正常的菜单
        List<SysMenu> menuList = list(lambdaQueryWrapper);

        if (!menuList.isEmpty()) {
            List<TreeNode<SysMenu>> treeNodeList = menuList.stream().map(menu -> {
                TreeNode<SysMenu> menuEntityTreeNode = new TreeNode<>();
                menuEntityTreeNode.setId(menu.getId());
                menuEntityTreeNode.setPid(menu.getPid());
                menuEntityTreeNode.setName(menu.getName());
                menuEntityTreeNode.setTarget(menu);

                return menuEntityTreeNode;
            }).collect(Collectors.toList());

            return TreeNodeUtil.buildTree(treeNodeList, 0L);
        }

        return new ArrayList<>();
    }

    @Override
    public List<SysMenu> listByRoleId(Long roleId) {
        List<SysMenu> sysMenus = roleMenuService.listByRoleId(Collections.singletonList(roleId));
        if (sysMenus != null && !sysMenus.isEmpty()) {
            return sysMenus;
        }
        return null;
    }

    @Override
    public List<SysMenu> listByRoleId(List<Long> roleIds) {
        if (roleIds != null && !roleIds.isEmpty()) {
            if (roleIds.contains(1L)) {
                LambdaQueryWrapper<SysMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(SysMenu::getStatus, 1);
                return list(lambdaQueryWrapper);
            }
            return roleMenuService.listByRoleId(roleIds);
        }
        return null;
    }

    /**
     * 校验菜单数据
     * @param sysMenu 菜单数据
     */
    private void validate(SysMenu sysMenu) {
        if (sysMenu.getPid() > 0) {
            SysMenu parentMenu = getById(sysMenu.getPid());
            if (Objects.equals(parentMenu.getType(), SysMenuTypeEnum.DIRECTORY.getType()) && Objects.equals(sysMenu.getType(), SysMenuTypeEnum.BUTTON.getType())) {
                throw new LogicHandleException("目录节点只允许添加目录或菜单节点");
            }

            if (Objects.equals(parentMenu.getType(), SysMenuTypeEnum.MENU.getType()) && !Objects.equals(sysMenu.getType(), SysMenuTypeEnum.BUTTON.getType())) {
                throw new LogicHandleException("菜单节点只允许添加按钮节点");
            }

            if (Objects.equals(parentMenu.getType(), SysMenuTypeEnum.BUTTON.getType())) {
                throw new LogicHandleException("按钮节点下面不允许添加任何节点");
            }
        }
    }
}
